#pragma once
#include <vector>
#include <memory>
#include <thread>
#include <mutex>
#include <cerrno>
#include <sys/eventfd.h>
#include <unistd.h>
#include "Channel.hpp"
#include "Poller.hpp"
#include "TimeWheel.hpp"

using Functor = std::function<void()>;
class EventLoop
{
private:
    std::thread::id _thread_id; // 线程ID
    int _event_fd;              // eventfd唤醒IO事件监控有可能导致的阻塞
    std::unique_ptr<Channel> _event_channel;
    Poller _poller;              // 进行所有描述符的事件监控
    std::vector<Functor> _tasks; // 任务池
    std::mutex _mutex;           // 实现任务池操作的线程安全
    TimeWheel _timer_wheel;      // 定时器模块

    static int CreateEventFd()
    {
        int evfd = ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
        if (evfd < 0)
        {
            std::cerr << "CREATE EVENTFD FAILED!!" << std::endl;
            abort();
        }
        return evfd;
    }

    void ReadEventFd()
    {
        uint64_t res = 0;
        int ret = ::read(_event_fd, &res, sizeof(res));
        if (ret < 0)
        {
            // EINTR -- 被信号打断；EAGAIN -- 表示无数据可读
            if (errno == EINTR || errno == EAGAIN)
            {
                return;
            }
            std::cerr << "READ EVENTFD FAILED!!" << std::endl;
            abort();
        }
    }

    void WriteEventFd()
    {
        uint64_t val = 1;
        int ret = ::write(_event_fd, &val, sizeof(val));
        if (ret < 0)
        {
            // EINTR -- 被信号打断；EAGAIN -- 表示无数据可读
            if (errno == EINTR)
            {
                return;
            }
            std::cerr << "WRITE EVENTFD FAILED!!" << std::endl;
            abort();
        }
    }

    void RunAllTask()
    {
        std::vector<Functor> tasks;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            tasks.swap(_tasks);
        }

        for (auto task : tasks)
            task();
    }

public:
    EventLoop()
        : _thread_id(std::this_thread::get_id()),
          _event_fd(CreateEventFd()),
          _event_channel(new Channel(this, _event_fd)),
          _timer_wheel(this)
    {
        _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEventFd, this));
        _event_channel->EnableRead();
    }
    ~EventLoop() {}

    // 三步走--事件监控-》就绪事件处理-》执行任务
    void Start()
    {
        while (true)
        {
            // 事件监控
            std::vector<Channel *> activates;
            _poller.Poll(&activates);
            // 就绪事件处理
            for (auto &channel : activates)
            {
                channel->HandleEvents();
            }
            // 执行任务
            RunAllTask();
        }
    }

    // 用于判断当前线程是否是EventLoop对应的线程；
    bool IsInLoop() { return _thread_id == std::this_thread::get_id(); }

    // 判断将要执行的任务是否处于当前线程中，如果是则执行，不是则压入队列。
    void RunInLoop(const Functor &cb)
    {
        if (IsInLoop())
        {
            cb();
        }
        else
        {
            QueueInLoop(cb);
        }
    }

    // 将操作压入任务池
    void QueueInLoop(const Functor &cb)
    {
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _tasks.push_back(cb);
        }
        WriteEventFd();
    }

    // 添加/修改描述符的事件监控
    void UpdateEvent(Channel *channel) { _poller.UpdateEvent(channel); }
    // 移除描述符的监控
    void RemoveEvent(Channel *channel) { _poller.RemoveEvent(channel); }

    // 添加任务
    void TimerAdd(uint64_t id, const TaskFunc &task, uint32_t delay) { _timer_wheel.TimerAdd(id, task, delay); }
    // 刷新任务
    void TimerRefresh(uint64_t id) { _timer_wheel.TimerRefresh(id); }
    // 取消任务
    void TimerCancal(uint64_t id) { _timer_wheel.TimerCancal(id); }

    bool HasTimer(uint64_t id) { return _timer_wheel.HasTimer(id); }
};